﻿#include "TradeApiSpi.h"
#include <iostream>
#ifdef __linux__
#include <cstring>
#endif
#include "CTPLoginAccount.h"
#include "OptionManager.h"

TradeApiSpi::TradeApiSpi(CThostFtdcTraderApi *tradeApi)
	//: m_blocker(nullptr)
{
	m_api = tradeApi;
	m_RspQryInstrumentFunc = nullptr;
	m_RspQryInvestorPositionFunc = nullptr;
	m_RspQryTradingAccountFunc = nullptr;
	m_TradeFeedFunc = nullptr;
	m_AuthenticateSuc = false;

	std::string ctpAccountFile = OptionManager::Instance().GetCTPTradeAccountSettingFile();
	CTPLogin::TradeAccount account(QString::fromLocal8Bit(ctpAccountFile.c_str()));
	m_ctpUsr.User_BrokerID = account.GetBrokerID();
	m_ctpUsr.UserId = account.GetUserID();
	m_ctpUsr.User_PWD = account.GetPassword();
	account.GetUrlList(m_ctpUsr.Trade_IPs);
	m_ctpUsr.U_AppID = account.GetAppID();
	m_ctpUsr.U_AuthCode = account.GetAuthCode();
	m_ctpUsr.U_InvestorID = account.GetInvestorID();
	m_ctpUsr.User_ProductInfo = account.GetProductInfo();
}


TradeApiSpi::~TradeApiSpi()
{
}

void TradeApiSpi::SetRspQryInstrumentFunc(std::function<void(CThostFtdcInstrumentField *pInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)> pFunc)
{
	m_RspQryInstrumentFunc = pFunc;
}

void TradeApiSpi::SetRspQryInvestorPositionFunc(std::function<void(CThostFtdcInvestorPositionField *position, CThostFtdcRspInfoField *rsp_info, int req_id, bool is_last)> pFunc)
{
	m_RspQryInvestorPositionFunc = pFunc;
}

void TradeApiSpi::SetRspQryTradingAccountFunc(std::function<void(CThostFtdcTradingAccountField *trading_account, CThostFtdcRspInfoField *rsp_info, int req_id, bool is_last)> pFunc)
{
	m_RspQryTradingAccountFunc = pFunc;
}

void TradeApiSpi::SetTradeBackFunc(std::function<void(CThostFtdcTradeField *pTrade)> pFunc)
{
	m_TradeFeedFunc = pFunc;
}

void TradeApiSpi::OnFrontConnected()
{
	if (!m_ctpUsr.U_AuthCode.empty())
	{
		CThostFtdcReqAuthenticateField pBody;
		strncpy(pBody.BrokerID, m_ctpUsr.User_BrokerID.c_str(), sizeof(TThostFtdcBrokerIDType));
		strncpy(pBody.UserID, m_ctpUsr.UserId.c_str(), sizeof(TThostFtdcInvestorIDType));
		strncpy(pBody.UserProductInfo, m_ctpUsr.User_ProductInfo.c_str(), sizeof(TThostFtdcProductInfoType));
		strncpy(pBody.AuthCode, m_ctpUsr.U_AuthCode.c_str(), sizeof(TThostFtdcAuthCodeType));
		// CTP接口新加了穿透试认证
		strncpy(pBody.AppID, m_ctpUsr.U_AppID.c_str(), sizeof(TThostFtdcAppIDType));
		int res = m_api->ReqAuthenticate(&pBody, 1);
		printf("OnFrontConnected 前置连接完成 请求认证 ReqAuthenticate--%d\n", res);
	}
	else
	{
		CThostFtdcReqUserLoginField pBody;
		strncpy(pBody.BrokerID, m_ctpUsr.User_BrokerID.c_str(), sizeof(TThostFtdcBrokerIDType));
		strncpy(pBody.UserID, m_ctpUsr.UserId.c_str(), sizeof(TThostFtdcInvestorIDType));
		strncpy(pBody.Password, m_ctpUsr.User_PWD.c_str(), sizeof(TThostFtdcPasswordType));
		
		int res = m_api->ReqUserLogin(&pBody, 111);
		printf("跳过认证，直接登录ReqUserLogin--%d\n", res);
	}
	//m_blocker.BlockCTP(2000);
}

void TradeApiSpi::OnFrontDisconnected(int nReason)
{
	printf("TradeApiSpi::OnFrontDisconnected %02X\n", nReason);
	m_AuthenticateSuc = false;
}

void TradeApiSpi::OnRspAuthenticate(CThostFtdcRspAuthenticateField *pRspAuthenticateField, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	if (!bIsLast) {
		return;
	}
	if (isErrorRspInfo(pRspInfo))
	{
		std::cerr << "OnRspAuthenticate 认证错误--->>> ErrorID=" << pRspInfo->ErrorID << ", ErrorMsg=" << pRspInfo->ErrorMsg << std::endl;
		return;
	}
	CThostFtdcReqUserLoginField pBody;
	strncpy(pBody.BrokerID, m_ctpUsr.User_BrokerID.c_str(), sizeof(TThostFtdcBrokerIDType));
	strncpy(pBody.UserID, m_ctpUsr.UserId.c_str(), sizeof(TThostFtdcInvestorIDType));
	strncpy(pBody.Password, m_ctpUsr.User_PWD.c_str(), sizeof(TThostFtdcPasswordType));
	int res = m_api->ReqUserLogin(&pBody, 111);
	printf("OnRspAuthenticate 认证通过 登录请求 ReqUserLogin --%d\n", res);
	//m_blocker.BlockCTP(2000);
	m_AuthenticateSuc = true;
}

void TradeApiSpi::OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	if (!bIsLast) {
		return;
	}
	if (isErrorRspInfo(pRspInfo))
	{
		std::cerr << "登录错误--->>> ErrorID=" << pRspInfo->ErrorID << ", ErrorMsg=" << pRspInfo->ErrorMsg << std::endl;
		return;
	}
	// 结算单确认，CTP必须确认才能下单
	CThostFtdcQrySettlementInfoField settlement_req{};
	strncpy(settlement_req.BrokerID, m_ctpUsr.User_BrokerID.c_str(), sizeof(settlement_req.BrokerID));
	strncpy(settlement_req.InvestorID, m_ctpUsr.U_InvestorID.c_str(), sizeof(settlement_req.InvestorID));
	int res = m_api->ReqQrySettlementInfo(&settlement_req, 111);
	printf("OnRspUserLogin 登录成功，请求查询投资者结算结果 ReqQrySettlementInfo--%d\n", res);
	//m_blocker.BlockCTP(2000);
}

void TradeApiSpi::OnRspQrySettlementInfo(CThostFtdcSettlementInfoField *pSettlementInfo, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	if (!bIsLast) {
		return;
	}
	if (isErrorRspInfo(pRspInfo))
	{
		std::cerr << "OnRspQrySettlementInfo 查询投资者结算结果错误--->>> ErrorID=" << pRspInfo->ErrorID << ", ErrorMsg=" << pRspInfo->ErrorMsg << std::endl;
		return;
	}
	CThostFtdcSettlementInfoConfirmField confirm_req{};
	strncpy(confirm_req.BrokerID, m_ctpUsr.User_BrokerID.c_str(), sizeof(confirm_req.BrokerID));
	strncpy(confirm_req.InvestorID, m_ctpUsr.U_InvestorID.c_str(), sizeof(confirm_req.InvestorID));

	int res = m_api->ReqSettlementInfoConfirm(&confirm_req, 112);
	printf("OnRspQrySettlementInfo 请求查询投资者结算结果返回，投资者结算结果确认ReqSettlementInfoConfirm --%d\n", res);
	//m_blocker.BlockCTP(2000);
}

void TradeApiSpi::OnRspSettlementInfoConfirm(CThostFtdcSettlementInfoConfirmField *pSettlementInfoConfirm, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	if (!bIsLast) {
		return;
	}
	printf("投资者结算结果确认  ");
	if (isErrorRspInfo(pRspInfo))
	{
		//std::cerr << "OnRspSettlementInfoConfirm 投资者结算结果确认错误--->>> ErrorID=" << pRspInfo->ErrorID << ", ErrorMsg=" << pRspInfo->ErrorMsg << std::endl;
		Blocker::Stop(m_blocker);
		return;
	}
	printf("\n");
	//m_blocker.BlockCTP(2000);
}

void TradeApiSpi::OnRspQryInvestor(CThostFtdcInvestorField *pInvestor, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	printf("TradeApiSpi::OnRspQryInvestor\n");
}

void TradeApiSpi::OnRspUserPasswordUpdate(CThostFtdcUserPasswordUpdateField *pUserPasswordUpdate, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	printf("TradeApiSpi::OnRspUserPasswordUpdate\n");
}

void TradeApiSpi::OnRspOrderInsert(CThostFtdcInputOrderField *pInputOrder, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	std::cerr << "--->>> " << "OnRspOrderInsert" << std::endl;
	isErrorRspInfo(pRspInfo);
}

void TradeApiSpi::OnErrRtnOrderInsert(CThostFtdcInputOrderField *pInputOrder, CThostFtdcRspInfoField *pRspInfo)
{
	std::cerr << "--->>> " << "OnErrRtnOrderInsert" << std::endl;
	isErrorRspInfo(pRspInfo);
}

void TradeApiSpi::OnRspOrderAction(CThostFtdcInputOrderActionField *pInputOrderAction, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	printf("TradeApiSpi::OnRspOrderAction\n");
}

void TradeApiSpi::OnErrRtnOrderAction(CThostFtdcOrderActionField *pOrderAction, CThostFtdcRspInfoField *pRspInfo)
{
	printf("TradeApiSpi::OnErrRtnOrderAction\n");
}

void TradeApiSpi::OnRspQryOrder(CThostFtdcOrderField *order, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	if (order && (order->OrderStatus == THOST_FTDC_OST_NoTradeQueueing ||
		order->OrderStatus == THOST_FTDC_OST_PartTradedQueueing)) {
		//LOG_INFO(
		//	"[CtpTradeApi::OnRspQryOrder] Cancel all orders on startup. Ticker: "
		//	"{}.{}, OrderSysID: {}, OriginalVolume: {}, Traded: {}, StatusMsg: {}",
		//	order->InstrumentID, order->ExchangeID, order->OrderSysID, order->VolumeTotalOriginal,
		//	order->VolumeTraded, gb2312_to_utf8(order->StatusMsg));
		printf("OnRspQryOrder %s:%s:%s\n", order->ExchangeID, order->InstrumentID, order->OrderSysID);

		CThostFtdcInputOrderActionField req{};
		strncpy(req.ExchangeID, order->ExchangeID, sizeof(req.ExchangeID));
		strncpy(req.OrderSysID, order->OrderSysID, sizeof(req.OrderSysID));
		strncpy(req.BrokerID, m_ctpUsr.User_BrokerID.c_str(), sizeof(req.BrokerID));
		strncpy(req.InvestorID, m_ctpUsr.U_InvestorID.c_str(), sizeof(req.InvestorID));
		req.ActionFlag = THOST_FTDC_AF_Delete;

		if (m_api->ReqOrderAction(&req, 300) != 0)
			printf("[CtpTradeApi::OnRspQryOrder] Failed to call ReqOrderAction");
		//m_blocker.BlockCTP(2000);
	}
}

void TradeApiSpi::OnRtnOrder(CThostFtdcOrderField *order)
{
	//printf("TradeApiSpi::OnRtnOrder\n");
	if (order == nullptr)
	{
		return;
	}
	// 过滤不是自己的订单
	if (order->InvestorID != m_ctpUsr.U_InvestorID) {
		return;
	}
	//m_waitSemaphor.Unlock();
	std::cout << "TradeApiSpi::OnRtnOrder " << order->StatusMsg << std::endl;
	// 被拒单或撤销被拒，回调相应函数
	if (order->OrderSubmitStatus == THOST_FTDC_OSS_InsertRejected) {
		//OrderRejectedRsp rsp{ order_id, gb2312_to_utf8(order->StatusMsg) };
		//gateway_->OnOrderRejected(rsp);
		return;
	}
	else if (order->OrderSubmitStatus == THOST_FTDC_OSS_CancelRejected) {
		//OrderCancelRejectedRsp rsp = { order_id, gb2312_to_utf8(order->StatusMsg) };
		//gateway_->OnOrderCancelRejected(rsp);
		return;
	}
	else if ((order->OrderSubmitStatus == THOST_FTDC_OSS_InsertSubmitted &&
		order->OrderStatus != THOST_FTDC_OST_Canceled) ||
		order->OrderSubmitStatus == THOST_FTDC_OSS_CancelSubmitted) {
		return;
	}

	if (order->OrderStatus == THOST_FTDC_OST_Unknown ||
		order->OrderStatus == THOST_FTDC_OST_NoTradeNotQueueing)
		return;

	// 处理撤单
	if (order->OrderStatus == THOST_FTDC_OST_PartTradedNotQueueing ||
		order->OrderStatus == THOST_FTDC_OST_Canceled) {
		//OrderCanceledRsp rsp = { order_id, order->VolumeTotalOriginal - order->VolumeTraded };
		//gateway_->OnOrderCanceled(rsp);
	}
	else if (order->OrderStatus == THOST_FTDC_OST_NoTradeQueueing) {
		//OrderAcceptedRsp rsp = { order_id };
		//gateway_->OnOrderAccepted(rsp);
	}
}

void TradeApiSpi::OnRspQryTrade(CThostFtdcTradeField *pTrade, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	if (pTrade == nullptr)
	{
		return;
	}
	printf("OnRspQryTrade %s:%s:%s\n", pTrade->ExchangeID, pTrade->InstrumentID, pTrade->OrderSysID);
}

void TradeApiSpi::OnRtnTrade(CThostFtdcTradeField *pTrade)
{
	if (pTrade == nullptr)
	{
		return;
	}
	//printf("OnRtnTrade %s:%s:%s\n", pTrade->ExchangeID, pTrade->InstrumentID, pTrade->OrderSysID);
	if (m_TradeFeedFunc != nullptr)
	{
		m_TradeFeedFunc(pTrade);
	}
}

void TradeApiSpi::OnRspQuoteInsert(CThostFtdcInputQuoteField *pInputQuote, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	printf("TradeApiSpi::OnRspQuoteInsert\n");
}

void TradeApiSpi::OnErrRtnQuoteInsert(CThostFtdcInputQuoteField *pInputQuote, CThostFtdcRspInfoField *pRspInfo)
{
	printf("TradeApiSpi::OnErrRtnQuoteInsert\n");
}

void TradeApiSpi::OnRspQryQuote(CThostFtdcQuoteField *pQuote, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	printf("TradeApiSpi::OnRspQryQuote\n");
}

void TradeApiSpi::OnRtnQuote(CThostFtdcQuoteField *pQuote)
{
	printf("TradeApiSpi::OnRtnQuote\n");
}

void TradeApiSpi::OnRspQuoteAction(CThostFtdcInputQuoteActionField *pInputQuoteAction, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	printf("TradeApiSpi::OnRspQuoteAction\n");
}

void TradeApiSpi::OnErrRtnQuoteAction(CThostFtdcQuoteActionField *pQuoteAction, CThostFtdcRspInfoField *pRspInfo)
{
	printf("TradeApiSpi::OnErrRtnQuoteAction\n");
}


void TradeApiSpi::OnRspQryInvestorPosition(CThostFtdcInvestorPositionField *pInvestorPosition, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	if (m_RspQryInvestorPositionFunc != nullptr)
	{
		m_RspQryInvestorPositionFunc(pInvestorPosition, pRspInfo, nRequestID, bIsLast);
	}
}

void TradeApiSpi::OnRspQryTradingAccount(CThostFtdcTradingAccountField *pTradingAccount, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	if (m_RspQryTradingAccountFunc != nullptr)
	{
		m_RspQryTradingAccountFunc(pTradingAccount, pRspInfo, nRequestID, bIsLast);
	}
}

void TradeApiSpi::OnRspQryInstrument(CThostFtdcInstrumentField *pInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	if (m_RspQryInstrumentFunc != nullptr)
	{
		m_RspQryInstrumentFunc(pInstrument, pRspInfo, nRequestID, bIsLast);
	}
}

void TradeApiSpi::OnRspError(CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
	isErrorRspInfo(pRspInfo);
}

void TradeApiSpi::OnRtnInstrumentStatus(CThostFtdcInstrumentStatusField *pInstrumentStatus)
{
	//printf("TradeApiSpi::OnRtnInstrumentStatus\n");
}

bool TradeApiSpi::isErrorRspInfo(CThostFtdcRspInfoField *pRspInfo)
{
	// 如果ErrorID != 0, 说明收到了错误的响应
	bool bResult = ((pRspInfo) && (pRspInfo->ErrorID != 0));
	if (bResult)
	{
		std::cerr << "--->>> ErrorID=" << pRspInfo->ErrorID << ", ErrorMsg=" << pRspInfo->ErrorMsg << std::endl;
	}
	return bResult;
}